<template>
  <div class="app-container">
    <SearchWithOperate
      :form-options="formOptions"
      btn-items="add,delete,export"
      @onSearch="handleQuery"
      @onAdd="handleAdd"
      @onDelete="handleDeleteAll"
      @onExport="handleExport"
    >
    </SearchWithOperate>

    <el-table v-loading="loading" tooltip-effect="light" :data="postList" border @selection-change="handleSelectionChange">
      <el-table-column type="selection" align="center" />
      <el-table-column label="岗位编号" prop="postId" width="100" />
      <el-table-column label="岗位编码" prop="postCode" />
      <el-table-column label="岗位名称" prop="postName" />
      <el-table-column label="岗位排序" prop="postSort" />
      <el-table-column label="状态" width="70" align="center" prop="status">
        <template #default="scope">
          <span class="stateShell">
            <div v-if="scope.row.status==='0'" class="common-prompt" style="background-color:#67C23A" />
            <div v-else class="common-prompt" style="background-color:#F56C6C" />
            <dict-tag :options="dict.type.status" :value="scope.row.status" />
          </span>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" align="center" prop="createTime" show-overflow-tooltip>
        <template #default="scope">
          <span>{{ parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
        <template #default="scope">
          <el-button v-hasPermi="['system:post:edit']" size="mini" type="primary" plain @click="handleUpdate(scope.row)">编辑</el-button>

          <el-button v-hasPermi="['system:post:remove']" size="mini" type="danger" plain @click="handleDelete(scope.row)">删除</el-button>

          <el-button size="mini" type="primary" plain @click="handleAuthUser(scope.row)">分配用户</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />

    <!-- 添加或修改岗位对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="60" append-to-body class="post-dialog">
      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="岗位名称" prop="postName">
              <el-input v-model="form.postName" placeholder="请输入岗位名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位编码" prop="postCode">
              <el-input v-model="form.postCode" placeholder="请输入编码名称" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="岗位顺序" prop="postSort">
              <el-input-number v-model="form.postSort" controls-position="right" :min="0" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位状态" prop="status">
              <el-radio-group v-model="form.status">
                <el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="部门" prop="">
              <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event)">展开/折叠</el-checkbox>
              <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event)">全选/全不选</el-checkbox>
              <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event)">父子联动</el-checkbox>
              <el-tree ref="dept" class="tree-border" :data="deptTreeList" show-checkbox node-key="id" :check-strictly="!form.deptCheckStrictly" empty-text="暂无数据" :props="defaultProps" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" :loading="submitLoading" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
    <auth-user ref="authUser" @ok="handleQuery" />
  </div>
</template>

<script>
import {
  addPost,
  changePostStatus,
  delPost,
  getPost,
  listPost,
  updatePost
} from '@/api/system/post'
import { postDeptTreeselect, treeselect } from '@/api/system/dept'
import { listRole } from '@/api/system/role'
import authUser from './AuthUser'

export default {
  name: 'Post',
  dicts: ['sys_normal_disable', 'status'],
  components: { authUser },
  data() {
    return {
      postId: null,
      // 遮罩层
      loading: true,
      submitLoading: false,
      // 选中数组
      ids: [],
      names: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 总条数
      total: 0,
      // 岗位表格数据
      postList: [],
      pageNum: 1,
      pageSize: 10,
      // 弹出层标题
      title: '',
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        postCode: undefined,
        postName: undefined,
        status: undefined
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        postName: [
          { required: true, message: '岗位名称不能为空', trigger: 'blur' }
        ],
        postCode: [
          { required: true, message: '岗位编码不能为空', trigger: 'blur' }
        ],
        postSort: [
          { required: true, message: '岗位顺序不能为空', trigger: 'blur' }
        ],
        remark: [
          { max: 500, message: '最多可以输入500个字符', trigger: 'change' }
        ]
      },
      postdeptIds: [],
      postAppRoles: [{ appId: null, roleIds: [] }],
      deptTreeList: [],
      deptMap: {},
      appRoles: {},
      oldPostRoleList: [],
      oldDeptPostList: [],
      newDeptPostList: [],
      menuExpand: false,
      menuNodeAll: false,
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      addDeptPostList: [],
      // 查询条件
      formOptions: [{
        label: '岗位编码:',
        prop: 'postCode',
        type: 'input',
        placeholder: '请输入岗位编码'
      }, {
        label: '岗位名称:',
        prop: 'postName',
        type: 'input',
        placeholder: '请输入岗位名称'
      }, {
        label: '状态:',
        prop: 'status',
        type: 'select',
        options: [],
        placeholder: '岗位状态'
      }]
    }
  },
  created() {
    this.init()
    this.getList()
  },
  mounted() {
    this.formOptions[2].options = this.dict.type.sys_normal_disable
  },
  methods: {
    isRole(row) {
      if (row) {
        return row.filter(function(data) {
          return data.status !== '1'
        })
      }
    },
    /**
     * 获取应用、组织、角色
     */
    init() {
      this.loadDeptList()
      this.loadRoleList()
    },
    loadDeptList() {
      treeselect({})
        .then(res => {
          this.deptTreeList = [...res.data]
          this.initTreeMap(this.deptTreeList)
        })
        .catch(err => {
          console.error(err)
        })
    },
    initTreeMap(deptTreeList) {
      this.deptMap = {}
      deptTreeList.forEach(node => {
        this.formatDeptTreeNode(node, null)
      })
    },
    formatDeptTreeNode(node, parentId) {
      node.parentId = parentId
      this.deptMap[node.id] = node
      const children = node.children || []
      if (children.length > 0) {
        children.forEach(item => {
          this.formatDeptTreeNode(item, node.id)
        })
      }
    },
    // 切换app 角色清空
    changeApp(row) {
      if (this.postId !== null) {
        row.roleIds = []
      } else {
        row.roleIds = []
      }
    },
    loadRoleList() {
      listRole({})
        .then(res => {
          this.appRoles = {}
          const roleList = [...(res.rows || [])]
          if (roleList.length > 0) {
            roleList.forEach(role => {
              let roleArr = this.appRoles[role.appId]
              if (!roleArr) {
                roleArr = []
                this.appRoles[role.appId] = roleArr
              }
              roleArr.push(role)
            })
          }
        })
        .catch(err => {
          console.error(err)
        })
    },
    /** 查询岗位列表 */
    getList() {
      this.loading = true
      listPost(this.queryParams).then(response => {
        this.postList = response.rows
        this.total = response.total
        this.loading = false
      })
    },
    // 取消按钮
    cancel() {
      this.open = false
      this.reset()
    },
    // 表单重置
    reset() {
      this.postId = null
      if (this.$refs.dept !== undefined) {
        this.$refs.dept.setCheckedKeys([])
      }
      this.form = {
        postId: undefined,
        postCode: undefined,
        postName: undefined,
        postSort: 0,
        status: '0',
        remark: undefined,
        deptCheckStrictly: true
      }
      this.oldPostRoleList = []
      this.oldDeptPostList = []
      this.postdeptIds = []
      this.postAppRoles = [{ appId: null, roleIds: [] }]
      this.resetForm('form')
      this.deptExpand = false
      this.deptNodeAll = false
    },
    /** 搜索按钮操作 */
    handleQuery(data) {
      this.queryParams = Object.assign(this.queryParams, data)
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm('queryForm')
      this.handleQuery()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.postId)
      this.names = selection.map(item => item.postName)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset()
      this.submitLoading = false
      this.open = true
      this.title = '添加岗位'
    },
    /** 分配用户按钮操作*/
    handleAuthUser: function(row) {
      this.$refs.authUser.show(row.postId)
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset()
      this.submitLoading = false
      const postId = row.postId
      this.postId = row.postId
      const postDeptTreeselect = this.getPostDeptTreeSelect(postId)
      getPost(postId).then(response => {
        this.form = response.data
        this.oldPostRoleList = response.data.postRoleList || []
        this.$nextTick(() => {
          postDeptTreeselect.then(res => {
            const extData = res.extData || {}
            this.oldDeptPostList = extData.checkedKeys || res.checkedKeys
            this.$refs.dept.setCheckedKeys(
              extData.checkedKeys || res.checkedKeys
            )
          })
        })
        // TODO 构造岗位角色关系
        this.buildPostAppRoles(this.oldPostRoleList, false)
        this.open = true
        this.title = '修改岗位'
      })
    },
    buildPostDeptIds(deptPostListdata) {
      this.postdeptIds = []
      if (deptPostListdata && deptPostListdata.length > 0) {
        deptPostListdata.forEach(item => {
          const data = []
          this.findDeptIdsWithParent(item.deptId, data)
          if (data.length > 0) {
            this.postdeptIds.push(data)
          }
        })
      }
    },
    findDeptIdsWithParent(deptId, data) {
      if (deptId && this.deptMap[deptId]) {
        data.splice(0, 0, deptId)
      }
      const node = this.deptMap[deptId]
      if (node) {
        const parentId = node.parentId
        if (parentId) {
          this.findDeptIdsWithParent(parentId, data)
        }
      }
    },
    buildPostAppRoles(postRoleList, flag, data) {
      this.postAppRoles = []
      if (postRoleList && postRoleList.length > 0) {
        const appIds = []
        const appRoleMap = {}
        postRoleList.forEach(item => {
          const appId = item.appId
          if (appIds.indexOf(appId) < 0) {
            appIds.push(appId)
            appRoleMap[appId] = []
          }
          const roleIds = appRoleMap[appId]
          roleIds.push(item.roleId)
        })

        appIds.forEach(appId => {
          this.postAppRoles.push({ appId: appId, roleIds: appRoleMap[appId] })
        })
      } else {
        if (flag) {
          this.postAppRoles.push({ appId: data, roleIds: [] })
        } else {
          this.postAppRoles.push({ appId: null, roleIds: [] })
        }
      }
    },
    buildUpdateParams(formData) {
      //  数据处理: 构造待删除数据、待增加数据（部门岗位关系、岗位角色关系）
      const result = { ...formData }
      result.deptPostList = []
      result.postRoleList = []

      const appRolesMap = {}
      const appRolesDel = []
      const deptPostDel = []

      if (this.postAppRoles.length > 0) {
        this.postAppRoles.forEach(item => {
          if (
            item.appId !== null &&
            item.appId !== undefined &&
            item.roleIds &&
            item.roleIds.length > 0
          ) {
            item.roleIds.forEach(roleId => {
              appRolesMap[item.appId + '_' + roleId] = {
                appId: item.appId,
                roleId: roleId,
                postId: result.postId
              }
            })
          }
        })
      }

      const oldAppRolesMap = {}
      // 检查待新增、删除数据(角色)
      if (this.oldPostRoleList && this.oldPostRoleList.length > 0) {
        this.oldPostRoleList.forEach(item => {
          oldAppRolesMap[item.appId + '_' + item.roleId] = item
        })

        // 检查待删除数据(角色)
        this.oldPostRoleList.forEach(item => {
          const postRole = appRolesMap[item.appId + '_' + item.roleId]
          if (!postRole) {
            appRolesDel.push(item.id)
          }
        })
      }

      // 检查待新增数据(角色)
      this.postAppRoles.forEach(item => {
        if (
          item.appId !== null &&
          item.appId !== undefined &&
          item.roleIds &&
          item.roleIds.length > 0
        ) {
          item.roleIds.forEach(roleId => {
            const dataKey = item.appId + '_' + roleId
            const postRole = oldAppRolesMap[dataKey]
            if (!postRole) {
              result.postRoleList.push(appRolesMap[dataKey])
            }
          })
        }
      })

      const oldDeptIdMap = {}
      if (this.oldDeptPostList && this.oldDeptPostList.length > 0) {
        this.oldDeptPostList.forEach(item => {
          oldDeptIdMap[item] = item
        })
      }

      const postDeptIdCache = []
      this.newDeptPostList = this.$refs.dept.getCheckedKeys()
      if (this.newDeptPostList.length > 0) {
        // 检查待新增数据（部门）
        this.newDeptPostList.forEach(item => {
          const deptId = item
          postDeptIdCache.push(deptId)
          if (!oldDeptIdMap[deptId]) {
            result.deptPostList.push({ deptId: deptId, postId: result.postId })
          }
        })
      }

      // 待删除数据（部门）
      this.oldDeptPostList.forEach(item => {
        const oldDeptId = item
        if (postDeptIdCache.indexOf(oldDeptId) < 0) {
          deptPostDel.push(oldDeptIdMap[oldDeptId])
        }
      })
      result.deletedDeptPostIds = deptPostDel
      result.deletedPostRoleIds = appRolesDel
      return result
    },
    buildAddParams(formData) {
      // 数据处理
      const result = { ...formData }
      result.deptPostList = []
      result.postRoleList = []
      if (this.postAppRoles.length > 0) {
        this.postAppRoles.forEach(item => {
          if (
            item.appId !== null &&
            item.appId !== undefined &&
            item.roleIds &&
            item.roleIds.length > 0
          ) {
            item.roleIds.forEach(roleId => {
              result.postRoleList.push({
                appId: item.appId,
                roleId: roleId,
                postId: result.postId
              })
            })
          }
        })
      }
      this.addDeptPostList = this.$refs.dept.getCheckedKeys()
      if (this.addDeptPostList.length > 0) {
        this.addDeptPostList.forEach(item => {
          result.deptPostList.push({ deptId: item, postId: result.postId })
        })
      }
      return result
    },
    /** 提交按钮 */
    submitForm() {
      this.submitLoading = true
      this.$refs['form'].validate(valid => {
        if (valid) {
          if (this.form.postId !== null && this.form.postId !== undefined) {
            const updateParams = this.buildUpdateParams(this.form)
            updatePost(updateParams)
              .then(response => {
                this.$modal.msgSuccess('修改成功')
                this.open = false
                this.getList()
              })
              .catch(err => {
                this.submitLoading = false
                console.error(err)
              })
          } else {
            const addParams = this.buildAddParams(this.form)
            addPost(addParams)
              .then(response => {
                this.$modal.msgSuccess('新增成功')
                this.open = false
                this.getList()
              })
              .catch(err => {
                this.submitLoading = false
                console.error(err)
              })
          }
        } else {
          this.submitLoading = false
        }
      })
    },
    /** 批量删除 */
    handleDeleteAll() {
      if (this.ids.length > 0) {
        this.$modal
          .confirm('是否确认删除岗位名称为"' + this.names + '"的数据项？')
          .then(() => {
            return delPost(this.ids).then(() => {
              this.getList()
              this.$modal.msgSuccess('删除成功')
            })
          })
          .catch(() => {})
      } else {
        this.$message.warning('未选中数据')
      }
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      this.$modal
        .confirm('是否确认删除岗位名称为"' + row.postName + '"的数据项？')
        .then(function() {
          return delPost(row.postId)
        })
        .then(() => {
          this.getList()
          this.$modal.msgSuccess('删除成功')
        })
        .catch(() => {})
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download(
        'system/post/export',
        {
          ...this.queryParams
        },
        `positioning_${new Date().getTime()}.xlsx`
      )
    },
    /** 修改菜单状态*/
    handleStatusChange(row) {
      const text = row.status === '0' ? '启用' : '停用'
      this.$modal
        .confirm('确认要"' + text + '""' + row.postName + '"岗位吗？')
        .then(function() {
          return changePostStatus(row.postId, row.status)
        })
        .then(() => {
          this.$modal.msgSuccess(text + '成功')
        })
        .catch(function() {
          row.status = row.status === '0' ? '1' : '0'
        })
    },
    handleAddAppRole(row) {
      this.postAppRoles.push({ appId: '', roleIds: [] })
    },
    handleDeleteAppRole(idx, row) {
      if (this.postAppRoles.length < 1) {
        this.postAppRoles.push({ appId: '', roleIds: [] })
      } else if (this.postAppRoles.length === 1) {
        this.postAppRoles.splice(idx, 1, { appId: null, roleIds: [] })
      } else {
        this.postAppRoles.splice(idx, 1)
      }
    },
    // 树权限（展开/折叠）
    handleCheckedTreeExpand(value) {
      const treeList = this.deptTreeList
      for (let i = 0; i < treeList.length; i++) {
        this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value
      }
    },
    // 树权限（全选/全不选）
    handleCheckedTreeNodeAll(value) {
      this.$refs.dept.setCheckedNodes(value ? this.deptTreeList : [])
    },
    handleCheckedTreeConnect(value) {
      this.form.deptCheckStrictly = !!value
    },
    /** 根据角色ID查询部门树结构 */
    getPostDeptTreeSelect(postId) {
      return postDeptTreeselect(postId).then(response => {
        const extData = response.extData || {}
        this.deptTreeList = extData.depts || response.depts
        return response
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.post-dialog {
  .el-cascader,
  .el-select,
  .el-input-number {
    width: 100%;
  }

  .post-role-btn.el-button--mini {
    padding: 7px;
  }
}
</style>
